Skip to content

Conversation

@Zhenhang1213
Copy link
Contributor

No description provided.

This adds a new value auto to the possible values of the existing -mtp=
clang option which controls how the thread pointer is found. auto means
the same as soft if the target architecture doesn't support a hardware
thread pointer at all; otherwise it means the same as cp15.

This behavior is the default in gcc version 4.1.0 and later. The new
auto option is therefore also the default in clang, so this change
aligns clang with gcc.

Fixes llvm#123864.
…humb2

We follow GCC mtp=auto when arch is arm_arch6k and support thumb2
…humb2

We follow GCC mtp=auto when arch is arm_arch6k and support thumb2
@llvmbot llvmbot added clang Clang issues not falling into any other category backend:ARM clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' labels Mar 6, 2025
@llvmbot
Copy link
Member

llvmbot commented Mar 6, 2025

@llvm/pr-subscribers-clang-driver

@llvm/pr-subscribers-backend-arm

Author: Austin (Zhenhang1213)

Changes

Full diff: https://github.com/llvm/llvm-project/pull/130022.diff

5 Files Affected:

  • (modified) clang/docs/ReleaseNotes.rst (+4)
  • (modified) clang/include/clang/Driver/Options.td (+1-1)
  • (modified) clang/lib/Driver/ToolChains/Arch/ARM.cpp (+18-8)
  • (modified) clang/lib/Driver/ToolChains/Arch/ARM.h (+1)
  • (modified) clang/test/Driver/arm-thread-pointer.c (+21-1)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 7873c2048e53c..99ba3b0a848c5 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -124,6 +124,10 @@ Deprecated Compiler Flags
 Modified Compiler Flags
 -----------------------
 
+- The ARM AArch32 ``-mtp`` option accepts and defaults to ``auto``, a value of ``auto`` uses the best available method of providing the frame pointer supported by the hardware. This matches
+  the behavior of ``-mtp`` in gcc. This changes the default behavior for ARM targets that provide the ``TPIDRURO`` register as this will be used instead of a call to the ``__aeabi_read_tp``.
+  Programs that use ``__aeabi_read_tp`` but do not use the ``TPIDRURO`` register must use ``-mtp=soft``. Fixes #123864
+
 Removed Compiler Flags
 -------------------------
 
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 75b1c51445942..cce0a673f4b09 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -4729,7 +4729,7 @@ def mexecute_only : Flag<["-"], "mexecute-only">, Group<m_arm_Features_Group>,
 def mno_execute_only : Flag<["-"], "mno-execute-only">, Group<m_arm_Features_Group>,
   HelpText<"Allow generation of data access to code sections (ARM only)">;
 let Flags = [TargetSpecific] in {
-def mtp_mode_EQ : Joined<["-"], "mtp=">, Group<m_arm_Features_Group>, Values<"soft,cp15,tpidrurw,tpidruro,tpidrprw,el0,el1,el2,el3,tpidr_el0,tpidr_el1,tpidr_el2,tpidr_el3,tpidrro_el0">,
+def mtp_mode_EQ : Joined<["-"], "mtp=">, Group<m_arm_Features_Group>, Values<"soft,cp15,tpidrurw,tpidruro,tpidrprw,el0,el1,el2,el3,tpidr_el0,tpidr_el1,tpidr_el2,tpidr_el3,tpidrro_el0,auto">,
   HelpText<"Thread pointer access method. "
            "For AArch32: 'soft' uses a function call, or 'tpidrurw', 'tpidruro' or 'tpidrprw' use the three CP15 registers. 'cp15' is an alias for 'tpidruro'. "
            "For AArch64: 'tpidr_el0', 'tpidr_el1', 'tpidr_el2', 'tpidr_el3' or 'tpidrro_el0' use the five system registers. 'elN' is an alias for 'tpidr_elN'.">;
diff --git a/clang/lib/Driver/ToolChains/Arch/ARM.cpp b/clang/lib/Driver/ToolChains/Arch/ARM.cpp
index 3aee540d501be..b7d5b3a9a882a 100644
--- a/clang/lib/Driver/ToolChains/Arch/ARM.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/ARM.cpp
@@ -208,14 +208,22 @@ bool arm::useAAPCSForMachO(const llvm::Triple &T) {
 bool arm::isHardTPSupported(const llvm::Triple &Triple) {
   int Ver = getARMSubArchVersionNumber(Triple);
   llvm::ARM::ArchKind AK = llvm::ARM::parseArch(Triple.getArchName());
-  return Triple.isARM() || AK == llvm::ARM::ArchKind::ARMV6T2 ||
-         (Ver >= 7 && AK != llvm::ARM::ArchKind::ARMV8MBaseline);
+  return Triple.isARM() || (Ver >= 7 && AK != llvm::ARM::ArchKind::ARMV8MBaseline);
 }
 
+
+// We follow GCC mtp=auto when arch is arm_arch6k and support thumb2
+bool arm::isHardTPAndThumb2(const llvm::Triple &Triple) {
+  llvm::ARM::ArchKind AK = llvm::ARM::parseArch(Triple.getArchName());
+  return Triple.isARM() && AK >= llvm::ARM::ArchKind::ARMV6K && AK != llvm::ARM::ArchKind::ARMV8MBaseline;
+}
+
+
 // Select mode for reading thread pointer (-mtp=soft/cp15).
 arm::ReadTPMode arm::getReadTPMode(const Driver &D, const ArgList &Args,
                                    const llvm::Triple &Triple, bool ForAS) {
-  if (Arg *A = Args.getLastArg(options::OPT_mtp_mode_EQ)) {
+  Arg *A = Args.getLastArg(options::OPT_mtp_mode_EQ);
+  if (A && A->getValue() != StringRef("auto")) {
     arm::ReadTPMode ThreadPointer =
         llvm::StringSwitch<arm::ReadTPMode>(A->getValue())
             .Case("cp15", ReadTPMode::TPIDRURO)
@@ -239,7 +247,7 @@ arm::ReadTPMode arm::getReadTPMode(const Driver &D, const ArgList &Args,
       D.Diag(diag::err_drv_invalid_mtp) << A->getAsString(Args);
     return ReadTPMode::Invalid;
   }
-  return ReadTPMode::Soft;
+  return (isHardTPAndThumb2(Triple) ? ReadTPMode::TPIDRURO : ReadTPMode::Soft);
 }
 
 void arm::setArchNameInTriple(const Driver &D, const ArgList &Args,
@@ -574,12 +582,14 @@ llvm::ARM::FPUKind arm::getARMTargetFeatures(const Driver &D,
       A->ignoreTargetSpecific();
   }
 
-  if (getReadTPMode(D, Args, Triple, ForAS) == ReadTPMode::TPIDRURW)
+  arm::ReadTPMode TPMode = getReadTPMode(D, Args, Triple, ForAS);
+
+  if (TPMode == ReadTPMode::TPIDRURW)
     Features.push_back("+read-tp-tpidrurw");
-  if (getReadTPMode(D, Args, Triple, ForAS) == ReadTPMode::TPIDRURO)
-    Features.push_back("+read-tp-tpidruro");
-  if (getReadTPMode(D, Args, Triple, ForAS) == ReadTPMode::TPIDRPRW)
+  else if (TPMode == ReadTPMode::TPIDRPRW)
     Features.push_back("+read-tp-tpidrprw");
+  else if (TPMode == ReadTPMode::TPIDRURO)
+    Features.push_back("+read-tp-tpidruro");
 
   const Arg *ArchArg = Args.getLastArg(options::OPT_march_EQ);
   const Arg *CPUArg = Args.getLastArg(options::OPT_mcpu_EQ);
diff --git a/clang/lib/Driver/ToolChains/Arch/ARM.h b/clang/lib/Driver/ToolChains/Arch/ARM.h
index a23a8793a89e2..0641580900fd1 100644
--- a/clang/lib/Driver/ToolChains/Arch/ARM.h
+++ b/clang/lib/Driver/ToolChains/Arch/ARM.h
@@ -57,6 +57,7 @@ FloatABI getARMFloatABI(const Driver &D, const llvm::Triple &Triple,
 void setFloatABIInTriple(const Driver &D, const llvm::opt::ArgList &Args,
                          llvm::Triple &triple);
 bool isHardTPSupported(const llvm::Triple &Triple);
+bool isHardTPAndThumb2(const llvm::Triple &Triple);
 ReadTPMode getReadTPMode(const Driver &D, const llvm::opt::ArgList &Args,
                          const llvm::Triple &Triple, bool ForAS);
 void setArchNameInTriple(const Driver &D, const llvm::opt::ArgList &Args,
diff --git a/clang/test/Driver/arm-thread-pointer.c b/clang/test/Driver/arm-thread-pointer.c
index 5521e1865b276..b487a8d83fe34 100644
--- a/clang/test/Driver/arm-thread-pointer.c
+++ b/clang/test/Driver/arm-thread-pointer.c
@@ -42,4 +42,24 @@
 
 // RUN: %clang --target=armv7-linux -### -S %s 2>&1 | \
 // RUN: FileCheck -check-prefix=ARMv7_THREAD_POINTER_NON %s
-// ARMv7_THREAD_POINTER_NON-NOT: "-target-feature" "+read-tp-tpidruro"
+// ARMv7_THREAD_POINTER_NON: "-target-feature" "+read-tp-tpidruro"
+
+// RUN: %clang --target=armv7-linux -mtp=auto -### -S %s 2>&1 | \
+// RUN: FileCheck -check-prefix=ARMv7_THREAD_POINTER_Auto %s
+// ARMv7_THREAD_POINTER_Auto: "-target-feature" "+read-tp-tpidruro"
+
+// RUN: %clang --target=armv5t-linux -mtp=auto -### -S %s 2>&1 | \
+// RUN: FileCheck -check-prefix=ARMv5t_THREAD_POINTER_Auto %s
+// ARMv5t_THREAD_POINTER_Auto-NOT: "-target-feature" "+read-tp-tpidruro"
+
+// RUN: %clang --target=armv6k-linux -mtp=auto -### -S %s 2>&1 | \
+// RUN: FileCheck -check-prefix=ARMv6k_THREAD_POINTER_Auto %s
+// ARMv6k_THREAD_POINTER_Auto: "-target-feature" "+read-tp-tpidruro"
+
+// RUN: %clang --target=armv6-linux -mtp=auto -### -S %s 2>&1 | \
+// RUN: FileCheck -check-prefix=ARMv6_THREAD_POINTER_Auto %s
+// ARMv6_THREAD_POINTER_Auto-NOT: "-target-feature" "+read-tp-tpidruro"
+
+// RUN: %clang --target=armv6kz-linux -mtp=auto -### -S %s 2>&1 | \
+// RUN: FileCheck -check-prefix=ARMv6kz_THREAD_POINTER_Auto %s
+// ARMv6kz_THREAD_POINTER_Auto: "-target-feature" "+read-tp-tpidruro"

@llvmbot
Copy link
Member

llvmbot commented Mar 6, 2025

@llvm/pr-subscribers-clang

Author: Austin (Zhenhang1213)

Changes

Full diff: https://github.com/llvm/llvm-project/pull/130022.diff

5 Files Affected:

  • (modified) clang/docs/ReleaseNotes.rst (+4)
  • (modified) clang/include/clang/Driver/Options.td (+1-1)
  • (modified) clang/lib/Driver/ToolChains/Arch/ARM.cpp (+18-8)
  • (modified) clang/lib/Driver/ToolChains/Arch/ARM.h (+1)
  • (modified) clang/test/Driver/arm-thread-pointer.c (+21-1)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 7873c2048e53c..99ba3b0a848c5 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -124,6 +124,10 @@ Deprecated Compiler Flags
 Modified Compiler Flags
 -----------------------
 
+- The ARM AArch32 ``-mtp`` option accepts and defaults to ``auto``, a value of ``auto`` uses the best available method of providing the frame pointer supported by the hardware. This matches
+  the behavior of ``-mtp`` in gcc. This changes the default behavior for ARM targets that provide the ``TPIDRURO`` register as this will be used instead of a call to the ``__aeabi_read_tp``.
+  Programs that use ``__aeabi_read_tp`` but do not use the ``TPIDRURO`` register must use ``-mtp=soft``. Fixes #123864
+
 Removed Compiler Flags
 -------------------------
 
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 75b1c51445942..cce0a673f4b09 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -4729,7 +4729,7 @@ def mexecute_only : Flag<["-"], "mexecute-only">, Group<m_arm_Features_Group>,
 def mno_execute_only : Flag<["-"], "mno-execute-only">, Group<m_arm_Features_Group>,
   HelpText<"Allow generation of data access to code sections (ARM only)">;
 let Flags = [TargetSpecific] in {
-def mtp_mode_EQ : Joined<["-"], "mtp=">, Group<m_arm_Features_Group>, Values<"soft,cp15,tpidrurw,tpidruro,tpidrprw,el0,el1,el2,el3,tpidr_el0,tpidr_el1,tpidr_el2,tpidr_el3,tpidrro_el0">,
+def mtp_mode_EQ : Joined<["-"], "mtp=">, Group<m_arm_Features_Group>, Values<"soft,cp15,tpidrurw,tpidruro,tpidrprw,el0,el1,el2,el3,tpidr_el0,tpidr_el1,tpidr_el2,tpidr_el3,tpidrro_el0,auto">,
   HelpText<"Thread pointer access method. "
            "For AArch32: 'soft' uses a function call, or 'tpidrurw', 'tpidruro' or 'tpidrprw' use the three CP15 registers. 'cp15' is an alias for 'tpidruro'. "
            "For AArch64: 'tpidr_el0', 'tpidr_el1', 'tpidr_el2', 'tpidr_el3' or 'tpidrro_el0' use the five system registers. 'elN' is an alias for 'tpidr_elN'.">;
diff --git a/clang/lib/Driver/ToolChains/Arch/ARM.cpp b/clang/lib/Driver/ToolChains/Arch/ARM.cpp
index 3aee540d501be..b7d5b3a9a882a 100644
--- a/clang/lib/Driver/ToolChains/Arch/ARM.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/ARM.cpp
@@ -208,14 +208,22 @@ bool arm::useAAPCSForMachO(const llvm::Triple &T) {
 bool arm::isHardTPSupported(const llvm::Triple &Triple) {
   int Ver = getARMSubArchVersionNumber(Triple);
   llvm::ARM::ArchKind AK = llvm::ARM::parseArch(Triple.getArchName());
-  return Triple.isARM() || AK == llvm::ARM::ArchKind::ARMV6T2 ||
-         (Ver >= 7 && AK != llvm::ARM::ArchKind::ARMV8MBaseline);
+  return Triple.isARM() || (Ver >= 7 && AK != llvm::ARM::ArchKind::ARMV8MBaseline);
 }
 
+
+// We follow GCC mtp=auto when arch is arm_arch6k and support thumb2
+bool arm::isHardTPAndThumb2(const llvm::Triple &Triple) {
+  llvm::ARM::ArchKind AK = llvm::ARM::parseArch(Triple.getArchName());
+  return Triple.isARM() && AK >= llvm::ARM::ArchKind::ARMV6K && AK != llvm::ARM::ArchKind::ARMV8MBaseline;
+}
+
+
 // Select mode for reading thread pointer (-mtp=soft/cp15).
 arm::ReadTPMode arm::getReadTPMode(const Driver &D, const ArgList &Args,
                                    const llvm::Triple &Triple, bool ForAS) {
-  if (Arg *A = Args.getLastArg(options::OPT_mtp_mode_EQ)) {
+  Arg *A = Args.getLastArg(options::OPT_mtp_mode_EQ);
+  if (A && A->getValue() != StringRef("auto")) {
     arm::ReadTPMode ThreadPointer =
         llvm::StringSwitch<arm::ReadTPMode>(A->getValue())
             .Case("cp15", ReadTPMode::TPIDRURO)
@@ -239,7 +247,7 @@ arm::ReadTPMode arm::getReadTPMode(const Driver &D, const ArgList &Args,
       D.Diag(diag::err_drv_invalid_mtp) << A->getAsString(Args);
     return ReadTPMode::Invalid;
   }
-  return ReadTPMode::Soft;
+  return (isHardTPAndThumb2(Triple) ? ReadTPMode::TPIDRURO : ReadTPMode::Soft);
 }
 
 void arm::setArchNameInTriple(const Driver &D, const ArgList &Args,
@@ -574,12 +582,14 @@ llvm::ARM::FPUKind arm::getARMTargetFeatures(const Driver &D,
       A->ignoreTargetSpecific();
   }
 
-  if (getReadTPMode(D, Args, Triple, ForAS) == ReadTPMode::TPIDRURW)
+  arm::ReadTPMode TPMode = getReadTPMode(D, Args, Triple, ForAS);
+
+  if (TPMode == ReadTPMode::TPIDRURW)
     Features.push_back("+read-tp-tpidrurw");
-  if (getReadTPMode(D, Args, Triple, ForAS) == ReadTPMode::TPIDRURO)
-    Features.push_back("+read-tp-tpidruro");
-  if (getReadTPMode(D, Args, Triple, ForAS) == ReadTPMode::TPIDRPRW)
+  else if (TPMode == ReadTPMode::TPIDRPRW)
     Features.push_back("+read-tp-tpidrprw");
+  else if (TPMode == ReadTPMode::TPIDRURO)
+    Features.push_back("+read-tp-tpidruro");
 
   const Arg *ArchArg = Args.getLastArg(options::OPT_march_EQ);
   const Arg *CPUArg = Args.getLastArg(options::OPT_mcpu_EQ);
diff --git a/clang/lib/Driver/ToolChains/Arch/ARM.h b/clang/lib/Driver/ToolChains/Arch/ARM.h
index a23a8793a89e2..0641580900fd1 100644
--- a/clang/lib/Driver/ToolChains/Arch/ARM.h
+++ b/clang/lib/Driver/ToolChains/Arch/ARM.h
@@ -57,6 +57,7 @@ FloatABI getARMFloatABI(const Driver &D, const llvm::Triple &Triple,
 void setFloatABIInTriple(const Driver &D, const llvm::opt::ArgList &Args,
                          llvm::Triple &triple);
 bool isHardTPSupported(const llvm::Triple &Triple);
+bool isHardTPAndThumb2(const llvm::Triple &Triple);
 ReadTPMode getReadTPMode(const Driver &D, const llvm::opt::ArgList &Args,
                          const llvm::Triple &Triple, bool ForAS);
 void setArchNameInTriple(const Driver &D, const llvm::opt::ArgList &Args,
diff --git a/clang/test/Driver/arm-thread-pointer.c b/clang/test/Driver/arm-thread-pointer.c
index 5521e1865b276..b487a8d83fe34 100644
--- a/clang/test/Driver/arm-thread-pointer.c
+++ b/clang/test/Driver/arm-thread-pointer.c
@@ -42,4 +42,24 @@
 
 // RUN: %clang --target=armv7-linux -### -S %s 2>&1 | \
 // RUN: FileCheck -check-prefix=ARMv7_THREAD_POINTER_NON %s
-// ARMv7_THREAD_POINTER_NON-NOT: "-target-feature" "+read-tp-tpidruro"
+// ARMv7_THREAD_POINTER_NON: "-target-feature" "+read-tp-tpidruro"
+
+// RUN: %clang --target=armv7-linux -mtp=auto -### -S %s 2>&1 | \
+// RUN: FileCheck -check-prefix=ARMv7_THREAD_POINTER_Auto %s
+// ARMv7_THREAD_POINTER_Auto: "-target-feature" "+read-tp-tpidruro"
+
+// RUN: %clang --target=armv5t-linux -mtp=auto -### -S %s 2>&1 | \
+// RUN: FileCheck -check-prefix=ARMv5t_THREAD_POINTER_Auto %s
+// ARMv5t_THREAD_POINTER_Auto-NOT: "-target-feature" "+read-tp-tpidruro"
+
+// RUN: %clang --target=armv6k-linux -mtp=auto -### -S %s 2>&1 | \
+// RUN: FileCheck -check-prefix=ARMv6k_THREAD_POINTER_Auto %s
+// ARMv6k_THREAD_POINTER_Auto: "-target-feature" "+read-tp-tpidruro"
+
+// RUN: %clang --target=armv6-linux -mtp=auto -### -S %s 2>&1 | \
+// RUN: FileCheck -check-prefix=ARMv6_THREAD_POINTER_Auto %s
+// ARMv6_THREAD_POINTER_Auto-NOT: "-target-feature" "+read-tp-tpidruro"
+
+// RUN: %clang --target=armv6kz-linux -mtp=auto -### -S %s 2>&1 | \
+// RUN: FileCheck -check-prefix=ARMv6kz_THREAD_POINTER_Auto %s
+// ARMv6kz_THREAD_POINTER_Auto: "-target-feature" "+read-tp-tpidruro"

@Zhenhang1213 Zhenhang1213 deleted the fix_mtp branch March 6, 2025 09:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend:ARM clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' clang Clang issues not falling into any other category

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants